using System;
using System.IO;
using System.Text;
using System.Threading;
using Fornax020.Configuration;

namespace Fornax020.Logging
{
    /// <summary>
    /// @file Logger.cs
    /// @brief 日志管理类
    /// @details 提供统一的日志记录功能，支持文件输出和调试输出
    /// 
    /// 设计模式应用：
    /// 1. 单例模式：确保日志管理器的唯一性
    /// 2. 策略模式：可扩展的日志输出策略
    /// 3. 观察者模式：日志事件通知
    /// 
    /// @author Fornax020 Development Team
    /// @date 2024
    /// @version 1.0.0
    /// </summary>
    public sealed class Logger
    {
        #region 单例模式实现
        private static readonly Lazy<Logger> _instance = 
            new Lazy<Logger>(() => new Logger());
        
        /// <summary>
        /// @brief 获取日志实例
        /// @details 单例模式，确保全局只有一个日志实例
        /// @return 日志实例
        /// </summary>
        public static Logger Instance => _instance.Value;
        
        /// <summary>
        /// @brief 私有构造函数
        /// @details 防止外部实例化，确保单例模式
        /// </summary>
        private Logger()
        {
            InitializeLogger();
        }
        #endregion

        #region 日志级别枚举
        /// <summary>
        /// @brief 日志级别枚举
        /// @details 定义不同的日志级别
        /// </summary>
        public enum LogLevel
        {
            /// <summary>
            /// 调试信息
            /// </summary>
            DEBUG = 0,
            
            /// <summary>
            /// 一般信息
            /// </summary>
            INFO = 1,
            
            /// <summary>
            /// 警告信息
            /// </summary>
            WARNING = 2,
            
            /// <summary>
            /// 错误信息
            /// </summary>
            ERROR = 3,
            
            /// <summary>
            /// 致命错误
            /// </summary>
            FATAL = 4
        }
        #endregion

        #region 私有字段
        private readonly object _lockObject = new object();
        private LogLevel _currentLogLevel = LogLevel.INFO;
        private bool _enableFileLogging = true;
        private bool _enableDebugOutput = true;
        private string _logFilePath;
        private StreamWriter _logFileWriter;
        private readonly StringBuilder _logBuffer = new StringBuilder();
        #endregion

        #region 事件定义
        /// <summary>
        /// @brief 日志记录事件
        /// @details 当记录日志时触发的事件
        /// </summary>
        public event EventHandler<LogEventArgs> LogRecorded;
        #endregion

        #region 公共属性
        /// <summary>
        /// @brief 当前日志级别
        /// @details 控制日志输出的详细程度
        /// </summary>
        public LogLevel CurrentLogLevel
        {
            get => _currentLogLevel;
            set => _currentLogLevel = value;
        }
        
        /// <summary>
        /// @brief 是否启用文件日志
        /// @details 控制是否将日志写入文件
        /// </summary>
        public bool EnableFileLogging
        {
            get => _enableFileLogging;
            set => _enableFileLogging = value;
        }
        
        /// <summary>
        /// @brief 是否启用调试输出
        /// @details 控制是否输出到调试窗口
        /// </summary>
        public bool EnableDebugOutput
        {
            get => _enableDebugOutput;
            set => _enableDebugOutput = value;
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// @brief 初始化日志器
        /// @details 设置日志文件路径和初始化配置
        /// </summary>
        private void InitializeLogger()
        {
            try
            {
                // 确保日志目录存在
                if (!Directory.Exists(ApplicationConfiguration.PathConfig.LOG_DIRECTORY))
                {
                    Directory.CreateDirectory(ApplicationConfiguration.PathConfig.LOG_DIRECTORY);
                }
                
                // 设置日志文件路径
                string fileName = $"{ApplicationConfiguration.PathConfig.DEFAULT_LOG_FILE}_{DateTime.Now:yyyyMMdd}.txt";
                _logFilePath = Path.Combine(ApplicationConfiguration.PathConfig.LOG_DIRECTORY, fileName);
                
                // 初始化文件写入器
                InitializeFileWriter();
                
                // 从配置加载设置
                LoadConfiguration();
                
                Info("Logger initialized successfully");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Logger initialization failed: {ex.Message}");
            }
        }
        
        /// <summary>
        /// @brief 初始化文件写入器
        /// @details 创建日志文件的写入器
        /// </summary>
        private void InitializeFileWriter()
        {
            try
            {
                if (_enableFileLogging && !string.IsNullOrEmpty(_logFilePath))
                {
                    _logFileWriter = new StreamWriter(_logFilePath, true, Encoding.UTF8)
                    {
                        AutoFlush = true
                    };
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Failed to initialize file writer: {ex.Message}");
                _enableFileLogging = false;
            }
        }
        
        /// <summary>
        /// @brief 加载配置
        /// @details 从应用程序配置加载日志设置
        /// </summary>
        private void LoadConfiguration()
        {
            try
            {
                var config = ApplicationConfiguration.Instance;
                
                // 设置日志级别
                if (Enum.TryParse<LogLevel>(config.LogLevel, out LogLevel level))
                {
                    _currentLogLevel = level;
                }
                
                // 设置调试模式
                _enableDebugOutput = config.EnableDebugMode;
                
                // 设置文件日志
                _enableFileLogging = config.AutoSaveLog;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Failed to load logger configuration: {ex.Message}");
            }
        }
        
        /// <summary>
        /// @brief 格式化日志消息
        /// @details 将日志信息格式化为标准格式
        /// @param level 日志级别
        /// @param message 日志消息
        /// @param exception 异常信息
        /// @return 格式化后的日志消息
        /// </summary>
        private string FormatLogMessage(LogLevel level, string message, Exception exception = null)
        {
            var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
            var threadId = Thread.CurrentThread.ManagedThreadId;
            var levelStr = level.ToString().PadRight(7);
            
            var logMessage = $"[{timestamp}] [{levelStr}] [Thread-{threadId}] {message}";
            
            if (exception != null)
            {
                logMessage += $"\nException: {exception}";
            }
            
            return logMessage;
        }
        
        /// <summary>
        /// @brief 写入日志
        /// @details 将日志消息写入到各种输出目标
        /// @param level 日志级别
        /// @param message 日志消息
        /// @param exception 异常信息
        /// </summary>
        private void WriteLog(LogLevel level, string message, Exception exception = null)
        {
            // 检查日志级别
            if (level < _currentLogLevel)
            {
                return;
            }
            
            var formattedMessage = FormatLogMessage(level, message, exception);
            
            lock (_lockObject)
            {
                try
                {
                    // 输出到调试窗口
                    if (_enableDebugOutput)
                    {
                        System.Diagnostics.Debug.WriteLine(formattedMessage);
                    }
                    
                    // 写入文件
                    if (_enableFileLogging && _logFileWriter != null)
                    {
                        _logFileWriter.WriteLine(formattedMessage);
                    }
                    
                    // 触发事件
                    OnLogRecorded(new LogEventArgs(level, message, exception, DateTime.Now));
                }
                catch (Exception ex)
                {
                    // 如果日志记录失败，至少输出到调试窗口
                    System.Diagnostics.Debug.WriteLine($"Log writing failed: {ex.Message}");
                    System.Diagnostics.Debug.WriteLine($"Original message: {formattedMessage}");
                }
            }
        }
        #endregion

        #region 公共方法
        /// <summary>
        /// @brief 记录调试信息
        /// @details 记录调试级别的日志信息
        /// @param message 日志消息
        /// @param exception 异常信息（可选）
        /// </summary>
        public void Debug(string message, Exception exception = null)
        {
            WriteLog(LogLevel.DEBUG, message, exception);
        }
        
        /// <summary>
        /// @brief 记录一般信息
        /// @details 记录信息级别的日志信息
        /// @param message 日志消息
        /// @param exception 异常信息（可选）
        /// </summary>
        public void Info(string message, Exception exception = null)
        {
            WriteLog(LogLevel.INFO, message, exception);
        }
        
        /// <summary>
        /// @brief 记录警告信息
        /// @details 记录警告级别的日志信息
        /// @param message 日志消息
        /// @param exception 异常信息（可选）
        /// </summary>
        public void Warning(string message, Exception exception = null)
        {
            WriteLog(LogLevel.WARNING, message, exception);
        }
        
        /// <summary>
        /// @brief 记录错误信息
        /// @details 记录错误级别的日志信息
        /// @param message 日志消息
        /// @param exception 异常信息（可选）
        /// </summary>
        public void Error(string message, Exception exception = null)
        {
            WriteLog(LogLevel.ERROR, message, exception);
        }
        
        /// <summary>
        /// @brief 记录致命错误
        /// @details 记录致命错误级别的日志信息
        /// @param message 日志消息
        /// @param exception 异常信息（可选）
        /// </summary>
        public void Fatal(string message, Exception exception = null)
        {
            WriteLog(LogLevel.FATAL, message, exception);
        }
        
        /// <summary>
        /// @brief 刷新日志缓冲区
        /// @details 强制刷新所有日志输出
        /// </summary>
        public void Flush()
        {
            lock (_lockObject)
            {
                try
                {
                    _logFileWriter?.Flush();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"Failed to flush log: {ex.Message}");
                }
            }
        }
        
        /// <summary>
        /// @brief 关闭日志器
        /// @details 关闭所有日志输出，释放资源
        /// </summary>
        public void Close()
        {
            lock (_lockObject)
            {
                try
                {
                    Info("Logger closing");
                    _logFileWriter?.Close();
                    _logFileWriter?.Dispose();
                    _logFileWriter = null;
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"Failed to close logger: {ex.Message}");
                }
            }
        }
        #endregion

        #region 事件触发方法
        /// <summary>
        /// @brief 触发日志记录事件
        /// @param e 日志事件参数
        /// </summary>
        protected void OnLogRecorded(LogEventArgs e)
        {
            LogRecorded?.Invoke(this, e);
        }
        #endregion

        #region IDisposable实现
        /// <summary>
        /// @brief 释放资源
        /// @details 实现IDisposable接口，确保资源正确释放
        /// </summary>
        public void Dispose()
        {
            Close();
        }
        #endregion
    }

    #region 事件参数类
    /// <summary>
    /// @brief 日志事件参数
    /// @details 包含日志记录的详细信息
    /// </summary>
    public class LogEventArgs : EventArgs
    {
        /// <summary>
        /// 日志级别
        /// </summary>
        public Logger.LogLevel Level { get; }
        
        /// <summary>
        /// 日志消息
        /// </summary>
        public string Message { get; }
        
        /// <summary>
        /// 异常信息
        /// </summary>
        public Exception Exception { get; }
        
        /// <summary>
        /// 时间戳
        /// </summary>
        public DateTime Timestamp { get; }
        
        /// <summary>
        /// @brief 构造函数
        /// @param level 日志级别
        /// @param message 日志消息
        /// @param exception 异常信息
        /// @param timestamp 时间戳
        /// </summary>
        public LogEventArgs(Logger.LogLevel level, string message, Exception exception, DateTime timestamp)
        {
            Level = level;
            Message = message;
            Exception = exception;
            Timestamp = timestamp;
        }
    }
    #endregion
}
